feat: Support provider initialization and shutdown - #28
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| return if @client.initialized? | ||
|
|
||
| state = @client.data_source_status_provider.status.state | ||
| raise "the LaunchDarkly client was unable to initialize; the data source state is #{state}" |
There was a problem hiding this comment.
The OpenFeature SDK will catch this exception? I want to double check that raising is the expectation.
There was a problem hiding this comment.
Yes — raising is the mechanism the OpenFeature Ruby SDK expects. Configuration#init_provider wraps the init call in a rescue, dispatches PROVIDER_ERROR (which moves provider state to ERROR), and only re-raises — as ProviderInitializationError — when the caller used set_provider_and_wait. With set_provider the init runs on its own thread and the exception is swallowed after the error event (v0.6.5 configuration.rb):
def init_provider(provider, context, raise_on_error: false)
...
dispatch_provider_event(provider, ProviderEvent::PROVIDER_READY)
rescue => e
error_code = (e.error_code if e.respond_to?(:error_code) && e.error_code) || Provider::ErrorCode::GENERAL
dispatch_provider_event(provider, ProviderEvent::PROVIDER_ERROR, error_code:, message: e.message)
raise ProviderInitializationError.new(..., original_error: e) if raise_on_error
endSo a failed initialization ends in the ERROR state rather than FATAL, matching the mapping we settled on in the spec: the LaunchDarkly client can still serve whatever data it has, so the OpenFeature SDK should keep calling the provider. Note the SDK also reads error_code off the exception if it exposes one, so we could raise a custom error later if we want something more specific than GENERAL.
Co-Authored-By: rlamb@launchdarkly.com <4955475+kinyoklion@users.noreply.github.com>
f45d6c6 to
bc88a8b
Compare
Implements the OpenFeature provider lifecycle hooks so the OpenFeature SDK can reflect LaunchDarkly initialization failures and release resources.
Provider#init, which raises when the LaunchDarkly client did not initialize, so the OpenFeature SDK moves the provider toERRORinstead of reportingREADY.Provider#shutdown, which closes the LaunchDarkly client when the provider is replaced orOpenFeature::SDK.shutdownis called.Implementation details
Requirements
Related issues
Part of an audit of the LaunchDarkly OpenFeature providers against the current OpenFeature specification. Provider lifecycle (spec sections 2.4 / 1.7) was unimplemented here: initialization failures were invisible to the OpenFeature SDK, and shutting down the OpenFeature SDK leaked the LaunchDarkly client's connections and event processor.
Describe the solution you've provided
OpenFeature::SDK::Configurationcallsiniton providers that respond to it and dispatchesPROVIDER_READYon success, orPROVIDER_ERRORwheninitraises; it callsshutdownon providers that respond to it.initusesLDClient#initialized?and includes the data source state fromdata_source_status_providerin the raised error message for diagnosability.Describe alternatives you've considered
Deferring LaunchDarkly client construction to
init— rejected because it would change the meaning of the existing publicclientaccessor and the constructor'swait_for_secondsargument. Blocking insideiniton a data source status listener — rejected as redundant, since the constructor already waits, and later state changes are better delivered as provider events.Testing
bundle exec rake(RSpec + RuboCop) on Ruby 3.4: 57 examples, 0 failures; 12 files inspected, no offenses. Ruby 3.4 was used because the gemspec requires>= 3.4.@cursor review
Link to Devin session: https://app.devin.ai/sessions/0c452d209ec54b068ba120b4c92b8f6c
Requested by: @kinyoklion
Note
Overview
Implements OpenFeature provider lifecycle so the SDK can report LaunchDarkly init failures and release resources.
Provider#initno-ops if the client is already initialized; otherwise it raises with the data source state so OpenFeature can move the provider to ERROR instead of READY.Provider#shutdowncloses the LaunchDarkly client. Construction still happens in the constructor; a closed client cannot be restarted.Specs cover successful init, failed init, and shutdown.
Reviewed by Cursor Bugbot for commit bc88a8b. Bugbot is set up for automated code reviews on this repo. Configure here.